/*
** ############################################################################
**     Project   : osdee - Operative Systems Design for Embedded Envrionments
**     File      : pit.c
**     Revision  ; 1.0
**     Abstract  :
**         PIT control functions implementation.
**     Processor : MC9S12XEP100CVL
**     Version   : Component 01.042, Driver 01.05, CPU db: 3.00.036
**     Datasheet : MC9S12XEP100 Rev. 1.19 12/2008
**
**     Copyright : 2014 Fernando Rodriguez, Open source with out any responsability.
**     
**     mail      : frr@gmail.com
** ############################################################################
*/

#include "pit.h"
#include "Os_Types.h"

/* Mcu_vPIT0_Callback, function to be called upon timeout of PIT channel 0 */
tCallbackFunction mal_mcu_vPIT_Callbacks[PIT_SUPPORTED_CHANNELS];

UINT8 mal_mcu_u8PIT_Channel_mask[PIT_SUPPORTED_CHANNELS] = {1,2,4,8,16,32,64,128};

/*
** ===================================================================
**     Method      :  Mcu_vPTI_Initialize(void)
**
**     Description :
**         Global PIT Module initializations.
** ===================================================================
*/
void Mcu_vPIT_General_Initialize()
{
    /* PIT counter freeze while in Freeze mode */
    PITCFLMT_PITFRZ = 1u;
    
    /* Precalculated PIT microtimer 0 (For High resolution timmers)*/
    PITMTLD0 = PIT_MICROTIMER0_DIV;
    /* Precalculated PIT microtimer 1 (For High period timmers)*/
    PITMTLD1 = PIT_MICROTIMER1_DIV;
    
    /* Load 8-bit microtimer load register 0 into the 8-bit micro timer down-counter 0 */
    PITCFLMT_PFLMT0 = 1u;
    /* Load 8-bit microtimer load register 0 into the 8-bit micro timer down-counter 0 */
    PITCFLMT_PFLMT1 = 1u;
    
    /* Enable Periodic Interrup Timer */
    PITCFLMT_PITE       = 1u;
}

/*
** ===================================================================
**     Method      :  Mcu_vPTI_Initialize(tsPIT_Channel tChannel)
**
**     Description :
**         PIT Channel initialization.
** ===================================================================
*/
void Mcu_vPTI_Initialize(tsPIT_Channel* tChannel)
{
  UINT16 u16CountDown;
  UINT16 u16PITLD_Offset;     
  
  /* Select micro time base according with PIT_Type */
  if(tChannel->tType == PIT_Type_HihgResolution)
  {
    /*Set micro time base 0 - PITMTLD0 */
    PITMUX &= (~mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id]);
    /* Calculate PIT count down value */
    u16CountDown = (UINT16)(((UINT16)(tChannel->u32Period / CFG_MICROTIMER0_COUNT) * PIT_TIMER_FACTOR) - 1);
  }
  else
  {
    /*Set micro time base 1 - PITMTLD1 */
    PITMUX |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
    /* Calculate PIT count down value */
    u16CountDown = (UINT16)(((UINT16)(tChannel->u32Period / CFG_MICROTIMER1_COUNT) * PIT_TIMER_FACTOR) - 1);
  }
  
  /* Set PIT count down value */
  u16PITLD_Offset = 4 * tChannel->tChannel_Id;      /* PITLD Offset = (PITLDX (2) + PITCNTX (2)) * Channel */
  *(&PITLD0 + (2 * tChannel->tChannel_Id)) = u16CountDown; 
  
  /*Set callback function*/
  mal_mcu_vPIT_Callbacks[tChannel->tChannel_Id] = tChannel->tCallback;
}

/*
** ===================================================================
**     Method      :  Mcu_vPTI_Initialize(tsPIT_Channel tChannel)
**
**     Description :
**         Starts PIT Channel countdown.
** ===================================================================
*/
void Mcu_vPTI_Start(tsPIT_Channel* tChannel)
{
  /* Enables PIT channel */
  PITCE |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
  
  /* Load 16-bit timer load register 0 into the 16-bit timer down-counter 0 */
  PITFLT_PFLT0 |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
    
  /* Enable PIT channel interrupt */
  PITINTE |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
  
  /* Clear PTI channel interrupt flag*/
  PITTF |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
}

/*
** ===================================================================
**     Method      :  Mcu_vPTI_Initialize(tsPIT_Channel tChannel)
**
**     Description :
**         Stops PIT Channel countdown.
** ===================================================================
*/
void Mcu_vPTI_Stop(tsPIT_Channel* tChannel)
{
  /* Disable PIT channel */
  PITCE &= ~mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
  
	/* Disable PIT channel interrupt */
  PITINTE &= ~mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
  
  /* Clear PTI channel interrupt flag*/
  PITTF |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
}

/*
** ===================================================================
**     Method      :  Mcu_vPTI_Enable(tsPIT_Channel tChannel)
**
**     Description :
**         Enables PIT Interruptions handling
** ===================================================================
*/
void Mcu_vPTI_Enable(tsPIT_Channel* tChannel)
{  
  /* Clear PTI channel interrupt flag*/
  PITTF |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
  
  /* Enable PIT channel interrupt */
  PITINTE |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
}

/*
** ===================================================================
**     Method      :  Mcu_vPTI_Disable(tsPIT_Channel tChannel)
**
**     Description :
**         Disables PIT Interruptions handling.
** ===================================================================
*/
void Mcu_vPTI_Disable(tsPIT_Channel* tChannel)
{
	/* Disable PIT channel interrupt */
  PITINTE &= ~mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
  
  /* Clear PTI channel interrupt flag*/
  PITTF |= mal_mcu_u8PIT_Channel_mask[tChannel->tChannel_Id];
}

/***************************************************************************************************/

/*
** ===================================================================
**     Method      :  Mcu_vPIT_ChannelX_Isr(void)
**
**     Description :
**         PIT channel (0-7) ISR function implementation. 
**         All interrupts handled in Main CPU, no XGATE enabled.
** ===================================================================
*/
#pragma CODE_SEG __NEAR_SEG NON_BANKED

void OS_Entry_Mcu_vPIT_Channel0_Isr(void)
//ISR(Mcu_vPIT_Channel0_Isr)
{
  SaveContext();
  INTERRUPT_DISABLE();
  Mcu_vHandle_PIT_Interrupt(PIT0);
  DispatcherService();

}

void Mcu_vSWI_Isr(void)
{
  SaveContext();
  
  DispatcherService();
}

void Mcu_vPIT_Channel1_Isr(void)
{
  Mcu_vHandle_PIT_Interrupt(PIT1);
}

void Mcu_vPIT_Channel2_Isr(void)
{
  Mcu_vHandle_PIT_Interrupt(PIT2);
}

void Mcu_vPIT_Channel3_Isr(void)
{
  Mcu_vHandle_PIT_Interrupt(PIT3);
}

void Mcu_vPIT_Channel4_Isr(void)
{
  Mcu_vHandle_PIT_Interrupt(PIT4);
}

void Mcu_vPIT_Channel5_Isr(void)
{
  Mcu_vHandle_PIT_Interrupt(PIT5);
}

void Mcu_vPIT_Channel6_Isr(void)
{
  Mcu_vHandle_PIT_Interrupt(PIT6);
}

void Mcu_vPIT_Channel7_Isr(void)
{
  Mcu_vHandle_PIT_Interrupt(PIT7);
}
#pragma CODE_SEG DEFAULT

/*
** ===================================================================
**     Method      :  Mcu_vHandle_PIT_Interrupt(tePIT_Channel_Id tChannel_Id)
**
**     Description :
**         Wrapps PIT Channel interruption handling. 
**         Clears interruption flag, and calls specified Callback.
** ===================================================================
*/
void Mcu_vHandle_PIT_Interrupt(tePIT_Channel_Id tChannel_Id)
{
  /* Verify that Real Time Interrupt caused the interrupt */
  if( PITTF & mal_mcu_u8PIT_Channel_mask[tChannel_Id])
  {
    /*call callback function, if initialized*/
    if(mal_mcu_vPIT_Callbacks[tChannel_Id] != NULL)
    {
        mal_mcu_vPIT_Callbacks[tChannel_Id]();
    }
  }
  /* Clear the real time interrupt flag */
  PITTF |= mal_mcu_u8PIT_Channel_mask[tChannel_Id];  
}
